package hu.ngms.jpf.maven;

import gov.nasa.jpf.Config;
import gov.nasa.jpf.JPF;

import java.io.IOException;
import java.util.List;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

@Mojo(name = "jpftest")
public class JpfUnittestMojo extends AbstractMojo {

	@Parameter(required = true, defaultValue = "${project}")
	private org.apache.maven.project.MavenProject mavenProject;

	public void execute() throws MojoExecutionException, MojoFailureException {
		String cp = assembleClasspath();
		this.getLog().debug("Classpath: " + cp);

		String[] jpfInputConfig = createJpfInputConfig();
		Config config = JPF.createConfig(jpfInputConfig);
		config.put("+native_classpath", cp);
		config.put("+classpath", cp);
		// TODO Append configuration defined in jpf.properties
		this.getLog().debug("JPF config: " + config);

		JPF jpf = new JPF(config);
		this.getLog().debug("JPF configuration: " + jpf.getConfig());
		try {
			jpf.run();
		} catch (Exception e) {
			e.printStackTrace();
			throw new MojoFailureException(e.getMessage());
		}
		if (jpf.foundErrors()) {
			throw new MojoExecutionException("Test failure");
		}
	}

	private String[] createJpfInputConfig() throws MojoFailureException {
		JpfConfig jpfConfig = new JpfConfig();

		try {
			JavaClassFinder testFinder = new JavaClassFinder(mavenProject.getTestCompileSourceRoots(), "Test.java");
			List<String> unitTestClasses = testFinder.findClasses();
			jpfConfig.setTestClasses(unitTestClasses);
		} catch (IOException e) {
			throw new MojoFailureException(e.getMessage());
		}

		return jpfConfig.toArray();
	}

	private String assembleClasspath() {
		StringBuilder sb = new StringBuilder();
		Set<Artifact> artifacts = mavenProject.getDependencyArtifacts();
		for (Artifact a : artifacts) {
			sb.append(a.getFile().getAbsolutePath()).append(System.getProperty("path.separator"));
		}
		String classpath = sb.substring(0, sb.length() - 1);
		return classpath;
	}

}
